package task;



import message.Message;
import entity.User;
import util.SocketUtil;

import java.io.*;
import java.net.Socket;
import java.nio.charset.Charset;
import java.sql.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * 消息处理任务
 */
public class MessageProcessTask implements Runnable {

    private Socket client;
    public static String url="jdbc:mysql://localhost:3306/chat?ServerTimezone=Asia/Shanghai";
    public static String sqlusername="root";
    public static String sqlpassword="123456";
    public static String jdbc="com.mysql.cj.jdbc.Driver";

    public MessageProcessTask(Socket client) {
        this.client = client;
    }

    @Override
    public void run() {
        Message msg = SocketUtil.receiveMsg(client);
        System.out.println(msg);
        if (msg != null) {
            switch (msg.getAction()) {
                case "register":
                    try {
                        processRegister(msg);
                    } catch (SQLException e) {
                        throw new RuntimeException(e);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    }
                    break;
                case "login":
                    try {
                        processLogin(msg);
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException(e);
                    } catch (SQLException e) {
                        throw new RuntimeException(e);
                    }
                    break;
                case "forgetNext":
                    processForgetNext(msg);
                    break;
                case "changePassword":
                    try {
                        processChangePassword(msg);
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } catch (SQLException throwables) {
                        throwables.printStackTrace();
                    }
                    break;
                case "sendMessage":
                    try {
                        processSendMessage2User(msg);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    break;
                case "sendMessage2Group":
                    try {
                        processSendMessage2Group(msg);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    break;
                case "sendRedBag2User":
                    processSendRedBag2User(msg);
                    break;
                case "sendRedBag2Group":
                    processSendRedBag2Group(msg);
                    break;
                case "addFriend":
                    try {
                        processaddFriend(msg);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                    break;
            }
        }
    }
    /**
     * 注册功能
     * @param msg 信息中包含账号密码....等注册信息
     * 在文件（数据库）中判断账号是否已经存在即可
     */
    public void processRegister(Message msg) throws SQLException, ClassNotFoundException {
        User user=(User)msg.getData();
        Class.forName(jdbc);
        Connection conn= DriverManager.getConnection(url,sqlusername,sqlpassword);
        String sql="select * from user where username=?";
        PreparedStatement ps=conn.prepareStatement(sql);
        ps.setString(1, user.getUsername());
        ResultSet rs=ps.executeQuery();
        if(rs.next()){//数据库中存在这个账号
            SocketUtil.sendBack(client,0);
        }else{//不存在则将数据存进去
            String sql1="insert into user (username,password,isOnline) values (?,?,0)";
            PreparedStatement ps1=conn.prepareStatement(sql1);
            ps1.setString(1, user.getUsername());
            ps1.setString(2, user.getPassword());
            int rowAffect=ps1.executeUpdate();
            if(rowAffect>0){
                SocketUtil.sendBack(client,1);
            }else{
                SocketUtil.sendBack(client,0);
            }
        }
    }
    /**
     * 处理登录操作
     * @param msg
     */
    public void processLogin(Message msg) throws ClassNotFoundException, SQLException {
        User user=(User)msg.getData();
        Class.forName(jdbc);
        Connection conn=DriverManager.getConnection(url,sqlusername,sqlpassword);
        String sql="select username,password from user where username=? and password=?";
        PreparedStatement ps=conn.prepareStatement(sql);
        ps.setString(1, user.getUsername());
        ps.setString(2, user.getPassword());
        ResultSet rs=ps.executeQuery();
        if(rs.next()){//账户存在登录成功
            SocketUtil.sendBack(client,1);
        }else{//账户不存在登录失败
            SocketUtil.sendBack(client,0);
        }
    }

    /**
     * 处理忘记密码下一步操作
     * @param msg
     */
    public void processForgetNext(Message msg) {

    }

    /**
     * 处理修改密码操作
     * @param msg
     */
    public void processChangePassword(Message msg) throws ClassNotFoundException, SQLException {
        //获取传过来的账号和密码
        Map map= (Map) msg.getData();
        String username= (String) map.get("username");
        String password= (String) map.get("password");
        String password_new= (String) map.get("password_new");
        //在数据库中查找该用户
        Class.forName(jdbc);
        Connection conn=DriverManager.getConnection(url,sqlusername,sqlpassword);
        String sql="select username,password from user where username=? and password=?";
        PreparedStatement ps=conn.prepareStatement(sql);
        ps.setString(1, username);
        ps.setString(2, password);
        ResultSet rs=ps.executeQuery();
        if(rs.next()){//账户存在则开始修改账号密码
            sql="UPDATE user SET passwrod = ? WHERE username = ?";
            ps=conn.prepareStatement(sql);
            ps.setString(1, password_new);
            ps.setString(2, username);
            int rowAffect=ps.executeUpdate();
            if (rowAffect>0){
                //修改成功
                SocketUtil.sendBack(client,1);
            }else {
                //修改失败
                SocketUtil.sendBack(client,-1);
            }
        }else{//账户不存在,或者密码错误
            SocketUtil.sendBack(client,0);
        }
    }

    /**(无念无风)
     * 和好友聊天
     * @param msg(里面包含发送的信息和保存聊天记录的文件名)
     * 将聊天信息存到文件中即可
     */
    public void processSendMessage2User(Message msg) throws IOException {



        // 从Message对象中获取数据，这里的数据应该是一个Map
        Map<String, String> messageContent = (Map<String, String>) msg.getData();

        // 提取目标用户名和消息内容
        String goalUsername1 = messageContent.get("goalName1");
        String goalUsername2 = messageContent.get("goalName2");
        System.out.println(goalUsername1+"\n"+goalUsername2);

        String messageStr = messageContent.get("message");
        System.out.println(messageStr);
        //把聊天记录存到文件中（测试例）
        BufferedWriter writer1 = new BufferedWriter(new FileWriter("documents/ChatBox/Friend/"+goalUsername1+".txt", true));
        BufferedWriter writer2 = new BufferedWriter(new FileWriter("documents/ChatBox/Friend/"+goalUsername2+".txt", true));
        writer1.write(messageStr);
        writer2.write(messageStr);

        writer1.newLine();
        writer2.newLine();

        writer1.close();
        writer2.close();

    }

    /**(星璃)
     * 群聊
     * @param msg(里面包含发送的信息和保存聊天记录的文件名)
     * 将聊天信息存到文件中即可
     */
    public void processSendMessage2Group(Message msg) throws IOException {
        // 从Message对象中获取数据，这里的数据应该是一个Map
        Map<String, String> messageContent = (Map<String, String>) msg.getData();
        String groupName = messageContent.get("groupName");
            // 群聊，将消息发送给所有在线用户
            // 获取群聊文件的名称
            String groupFilename = "documents/ChatBox/Group/" + groupName + ".txt";
            // 读取群聊文件的内容
            BufferedWriter writer = new BufferedWriter(new FileWriter(groupFilename, true));
            String messageStr = messageContent.get("msg");
            writer.write(messageStr);
            writer.newLine();
            writer.close();
    }
    /**
     * 私发红包
     * @param msg
     */
    public void processSendRedBag2User(Message msg) {

    }
    /**
     * 群发红包
     * @param msg
     */
    public void processSendRedBag2Group(Message msg) {

    }

    /**(半知)
     * 添加好友
     * @param msg(包含当前用户和添加的用户)
     * 互相添加到彼此的好友列表当中（文件操作，以各自的账号+friends命名的好友文件）
     */
    public void processaddFriend(Message msg) throws IOException {
        HashMap<String,String> map= (HashMap<String, String>) msg.getData();
        String localUsername= (String) map.get("localUsername");
        String goalUsername= (String) map.get("goalUsername");
        //获取文件名
        String localFilename= "documents/FriendList/"+localUsername+".txt";
        String goalFilename= "documents/FriendList/"+goalUsername+".txt";
        // 读取本地用户的好友列表
        Set<String> localFriends = readFriendsFromFile(localFilename);
        // 读取目标用户的好友列表
        Set<String> goalFriends = readFriendsFromFile(goalFilename);



        //如果好友不在列表中就添加，在就不添加
        if (!localFriends.contains(goalUsername)){
            //添加目标用户到本地用户的好友列表
            appendFriendToFile(localFilename,goalFilename);
        }
        if (!goalFriends.contains(localUsername)){
            //添加本地用户到目标用户的好友列表
            appendFriendToFile(goalFilename,localUsername);
        }
    }

    //读取好友列表
    private Set<String> readFriendsFromFile(String filename) throws IOException {
        Set<String> friends = new HashSet<>();
        File file = new File(filename);
        if (file.exists()) {
            try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    friends.add(line.trim());
                }
            }
        }
        return friends;
    }

    /**
     * 将friend的用户名添加到 filename的好友列表中
     * @param filename
     * @param friend
     * @throws IOException
     */
    private void appendFriendToFile(String filename, String friend) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename,true))) {
                writer.write(friend);
                writer.newLine();
        }
    }
}
